#ifndef __IPERIPHERAL_H__
#define __IPERIPHERAL_H__

#include <string>
#include <functional>
#include "plat/nonecopyable.h"
#include "framework_global.h"
#include "soc/soc_comm_def.h"


/// @brief 外设接口 [静态外设，比如 GPIO]
class IPeripheral : public NoneCopyable
{
public:
    explicit IPeripheral();
    virtual ~IPeripheral();

public:
    inline int GetDeviceId(){return m_devId;}
    
    inline bool CheckDeviceId(){return m_devId >= 0;}

    template<class THANDLE>
    inline THANDLE* GetThisHandleAs()
    {
        return static_cast<THANDLE*>(m_socHandle);
    }

    inline void AttachHandle(void *handle)
    {
        m_socHandle = handle;
    }

    inline void ResetThisHandle()
    {
        m_socHandle = nullptr;
    }

protected:
    int m_devId = -1;

    //实例的硬件handle
    void *m_socHandle = nullptr; 
};

/// @brief 外设接口
template<class TInstance, int MAX_INSTANCE, int MAX_HANDLE = MAX_INSTANCE>
class IPeripheralEx : public IPeripheral
{
public:
    explicit IPeripheralEx(){}
    virtual ~IPeripheralEx(){}

public:
    inline static void AddInstance(int id, TInstance *instance)
    {
        //因为ID可以延后初始化，这里只做判断
        if(id < 0 && id >= MAX_INSTANCE)
        {
            return;
        }

        m_instances[id] = instance;
    }

    inline static TInstance* GetInstanceById(int id)
    {
        FW_ASSERT(id >= 0 && id < MAX_INSTANCE);

        return m_instances[id];
    }

    inline static TInstance* GetInstanceByHandle(void *handle)
    {
        for(int i = 0; i < MAX_INSTANCE; i++)
        {
            auto h = m_instances[i];
            if(h == nullptr)
                continue;

            if(h->m_socHandle == handle)
            {
                return m_instances[i];
            }
        }

        return nullptr;
    }

    template<class THANDLE>
    inline static THANDLE* GetHandleAs(int id)
    {
        FW_ASSERT(id >= 0 && id < MAX_INSTANCE);

        return static_cast<THANDLE*>(m_instances[id]->m_socHandle); 
    }

protected:
    template<class TID, class TINS>
    void InitPeripheral(TID id, TINS *ins, void *handle)
    {
        m_devId = (int)id;
        m_socHandle = handle;
        AddInstance(m_devId, ins);
    }

protected:
    static TInstance *m_instances[MAX_INSTANCE];
};

template<class TInstance, int MAX_INSTANCE, int MAX_HANDLE>
TInstance * IPeripheralEx<TInstance, MAX_INSTANCE, MAX_HANDLE>::m_instances[MAX_INSTANCE] = {0};

#endif // __IPERIPHERAL_H__